package glossos.parsing;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.File;
import java.io.FileFilter;
import java.io.Reader;
import java.io.StringReader;

@RunWith(MockitoJUnitRunner.class)
public class ReaderIteratorTestCase {

	ReaderIterator iterator;
	@Mock File fileMock;
	@Mock FileFilter filterMock;
	@Mock ReaderFactory factoryMock;
	
	@Test
	public void skipSingleFileFilteredOut() throws Exception {
		when(fileMock.isDirectory()).thenReturn(false);
		when(filterMock.accept(fileMock)).thenReturn(false);

		iterator = new ReaderIterator(fileMock, filterMock, factoryMock);
		
		assertFalse(iterator.hasNext());
	}
	
	@Test
	public void readerForSingleFileMatchingFilter() throws Exception {
		Reader reader1 = new StringReader("To be or not to be");
		
		when(fileMock.isDirectory()).thenReturn(false);
		when(factoryMock.readerFor(anyFile())).thenReturn(reader1);
		when(filterMock.accept(fileMock)).thenReturn(true);

		iterator = new ReaderIterator(fileMock, filterMock, factoryMock);
		
		assertTrue(iterator.hasNext());
		assertThat(iterator.next(), is(reader1));
		assertFalse(iterator.hasNext());
	}

	@Test
	public void readersForTwoFilesInDirectory() throws Exception {
		Reader reader1 = new StringReader("To be or not to be");
		Reader reader2 = new StringReader("Said the raven: nevermore!");
		
		when(fileMock.isDirectory()).thenReturn(true);
		when(fileMock.listFiles(filterMock)).thenReturn(new File[]{new File(""), new File("")});
		when(factoryMock.readerFor(anyFile())).thenReturn(reader1, reader2);
		when(filterMock.accept(fileMock)).thenReturn(true);
		
		iterator = new ReaderIterator(fileMock, filterMock, factoryMock);
		
		assertThat(iterator.next(), is(reader1));
		assertThat(iterator.next(), is(reader2));
		assertFalse(iterator.hasNext());
	}
		
	private File anyFile() {
		return (File) any();
	}
}
